/*
 * GL_MobileObject.h
 *
 * Created 6/9/2009 By Johnny Huynh
 *
 * Version 00.00.01 6/9/2009
 *
 * Copyright Information:
 * All content copyright © 2009 Johnny Huynh. All rights reserved.
 */
 
 // GL_MOBILEObject.h contains additional movement properties for an object
 
 #ifndef GL_MOBILEOBJECT_H
 #define GL_MOBILEOBJECT_H
 
 template< typename TYPENAME > class GL_MobileObject;
 
 typedef GL_MobileObject<GLfloat> GL_MobileObjectf;
 typedef GL_MobileObject<GLdouble> GL_MobileObjectd;
 
 #include "GL_Object.h"

 template< typename TYPENAME >
 class GL_MobileObject : public GL_Object<TYPENAME>
 {
 // Data Members
 protected:
    Vector3<TYPENAME> velocity;
    
 // Local Functions
 public:
    GL_MobileObject( std::vector< GL_Triangle<TYPENAME> > raw_triangles,
                               const TYPENAME& posX = 0.0f, const TYPENAME& posY = 0.0f, const TYPENAME& posZ = 0.0f,
                               const TYPENAME& Xx = 1.0f, const TYPENAME& Yx = 0.0f, const TYPENAME& Zx = 0.0f,
                               const TYPENAME& Xy = 0.0f,  const TYPENAME& Yy = 1.0f, const TYPENAME& Zy = 0.0f,
                               const TYPENAME& Xz = 0.0f,  const TYPENAME& Yz = 0.0f, const TYPENAME& Zz = 1.0f,
                               const TYPENAME& velocityX = 0.0f, const TYPENAME& velocityY = 0.0f, 
                               const TYPENAME& velocityZ = 0.0f );
    
    /*GL_MobileObject( const GL_Triangle<TYPENAME>* const& raw_triangles_Ptr, size_t size,
                               const TYPENAME& locX = 0.0f, const TYPENAME& locY = 0.0f, const TYPENAME& locZ = 0.0f,
                               const TYPENAME& Xx = 1.0f, const TYPENAME& Yx = 0.0f, const TYPENAME& Zx = 0.0f,
                               const TYPENAME& Xy = 0.0f,  const TYPENAME& Yy = 1.0f, const TYPENAME& Zy = 0.0f,
                               const TYPENAME& Xz = 0.0f,  const TYPENAME& Yz = 0.0f, const TYPENAME& Zz = 1.0f,
                               const TYPENAME& velocityX = 0.0f, const TYPENAME& velocityY = 0.0f, 
                               const TYPENAME& velocityZ = 0.0f );*/
    GL_MobileObject( const GL_MobileObject& mobj );
    //GL_MobileObject( const GL_Object& obj, const Vector3<TYPENAME>& velocity = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ) );
    GL_MobileObject( const GL_Object& obj, const Vector3<TYPENAME>& position = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ), 
                                           const Vector3<TYPENAME>& velocity = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ) );
    virtual ~GL_MobileObject();
    virtual inline GL_MobileObject<TYPENAME>& operator=( const GL_MobileObject<TYPENAME>& mobj );
    virtual inline void updateDisplacement( const TYPENAME& unit );
    inline void setVelocity( const Vector3<TYPENAME>& v ) { velocity = v; }
    inline const Vector3<TYPENAME>& getVelocity() { return velocity; }
    virtual inline void handleCollision(){ velocity = Vector3<TYPENAME>( 0.0f, 0.0f, 0.0f ); /*velocity = -velocity;*/ };
 
 // Private Functions
 private:
 
 // Friend Functions
 public:

 };

 /** LOCAL FUNCTIONS **/
 
 /**
  * Constructor
  */
 template <typename TYPENAME>
 GL_MobileObject<TYPENAME>::GL_MobileObject( std::vector< GL_Triangle<TYPENAME> > raw_triangles, 
                                 const TYPENAME& posX, const TYPENAME& posY, const TYPENAME& posZ,
                                 const TYPENAME& Xx, const TYPENAME& Yx, const TYPENAME& Zx,
                                 const TYPENAME& Xy, const TYPENAME& Yy, const TYPENAME& Zy,
                                 const TYPENAME& Xz, const TYPENAME& Yz, const TYPENAME& Zz,
                                 const TYPENAME& velocityX, const TYPENAME& velocityY, 
                                 const TYPENAME& velocityZ )
                                : GL_Object<TYPENAME>( raw_triangles,
                                                       posX, posY, posZ,
                                                       Xx, Yx, Zx,
                                                       Xy, Yy, Zy,
                                                       Xz, Yz, Zz ),
                                  velocity( velocityX, velocityY, velocityZ )
 {

 }

 /**
  * Alternative Constructor
  * The constructor takes in triangles pointer and the number of triangles.
  *
  * @param (const GL_Triangle<TYPENAME>* const&) triangles_Ptr - this can be the beginning address of an array
  * @param (size_t) size - the number of triangles point to by triangles_Ptr
  */
 /*template< typename TYPENAME >
 GL_Object<TYPENAME>::GL_Object( const GL_Triangle<TYPENAME>* const& raw_triangles_Ptr, size_t size, 
                                 const TYPENAME& locX, const TYPENAME& locY, const TYPENAME& locZ,
                                 const TYPENAME& Xx, const TYPENAME& Yx, const TYPENAME& Zx,
                                 const TYPENAME& Xy, const TYPENAME& Yy, const TYPENAME& Zy,
                                 const TYPENAME& Xz, const TYPENAME& Yz, const TYPENAME& Zz,
                                 const TYPENAME& velocityX, const TYPENAME& velocityY, 
                                 const TYPENAME& velocityZ )
                                : GL_Actor( locX, locY, locZ,
                                            Xx, Yx, Zx,
                                            Xy, Yy, Zy,
                                            Xz, Yz, Zz ),
                                  raw_triangles( raw_triangles_Ptr, raw_triangles_Ptr + size),
                                  triangles( raw_triangles_Ptr, raw_triangles_Ptr + size),
                                  obbtree( *this )
 {
    // notice that triangles_Ptr + 1 points to the next triangle.
    
    // if the orientation or position is not representative of the raw orientation and position
    if ( !orientation.isIdentityMatrix() ) 
        maintain( *this );  // recompute the triangles' orientation and positions
    else if ( !position.isZeroVector() )
        maintainPosition( *this );
    
    initializeOBBTree();
 }*/
 
 /**
  * Copy Constructor
  */
 template <typename TYPENAME>
 GL_MobileObject<TYPENAME>::GL_MobileObject( const GL_MobileObject& mobj )
                                            : GL_Object<TYPENAME>( mobj )
 {
    velocity = mobj.velocity;
 }
 
 /**
  * Copy Constructor
  */
 /*template <typename TYPENAME>
 GL_MobileObject<TYPENAME>::GL_MobileObject( const GL_Object& obj, const Vector3<TYPENAME>& velocity )
                                            : GL_Object<TYPENAME>( obj ), velocity( velocity )
 {
 
 }*/
 
 /**
  * Copy Constructor
  */
 template <typename TYPENAME>
 GL_MobileObject<TYPENAME>::GL_MobileObject( const GL_Object& obj, const Vector3<TYPENAME>& position, const Vector3<TYPENAME>& velocity )
                                            : GL_Object<TYPENAME>( obj ), velocity( velocity )
 {
    this->setPosition( position.x, position.y, position.z );
 #if IMPLEMENT_INTERPOLATION == 1
    this->previousPosition = position;
 #endif // IMPLEMENT_INTERPOLATION == 1
 }
 
 /**
  * Destructor
  */
 template <typename TYPENAME>
 GL_MobileObject<TYPENAME>::~GL_MobileObject()
 {
 
 }
 
 /**
  * operator=() copies the content of the specified mobile object to this mobile object.
  *
  * @param (const GL_MobileObject<TYPENAME>&) o
  */
 template <typename TYPENAME>
 inline GL_MobileObject<TYPENAME>& GL_MobileObject<TYPENAME>::operator=( const GL_MobileObject<TYPENAME>& mobj )
 {
    GL_Object<TYPENAME>::operator=( mobj );
    velocity = mobj.velocity;
    
    return *this;
 }
 
 /**
  * updateDisplacement() moves this object in the direction of the velocity by the specified unit.
  *
  * @param (const TYPENAME&) unit
  */
 template <typename TYPENAME>
 inline void GL_MobileObject<TYPENAME>::updateDisplacement( const TYPENAME& unit )
 {
    translate( velocity.x*unit, velocity.y*unit, velocity.z*unit );
 }
 
 /** FRIEND FUNCTIONS **/

 
 #endif // GL_MOBILEOBJECT_H